// package com.zzht.patrol.bp.calculate.utils;
//
// import cn.hutool.extra.spring.SpringUtil;
// import com.zzht.bp.common.util.ListUtils;
// import com.zzht.bp.trace.model.ClusterPoint;
// import com.zzht.bp.trace.model.Position;
// import com.zzht.bp.trace.util.PositionCluster;
// import com.zzht.patrol.bp.calculate.cache.Calculator;
// import com.zzht.patrol.bp.calculate.cache.StagnateBasket;
// import com.zzht.patrol.bp.calculate.cache.StagnateCal;
// import com.zzht.patrol.bp.calculate.service.IConfigService;
// import com.zzht.patrol.bp.calculate.service.ITaskComputeService;
// import com.zzht.patrol.collectivize.utils.TraceConfigHandler;
// import com.zzht.patrol.common.utils.IdLockUtils;
// import com.zzht.patrol.common.utils.SpringContextHolder;
// import lombok.extern.log4j.Log4j2;
// import org.apache.commons.lang.StringUtils;
// import org.locationtech.jts.geom.Position;
// import pers.zzz.coord.transform.exception.InvalidParametersException;
// import pers.zzz.coord.transform.exception.UnSupportedMethodException;
//
// import java.util.ArrayList;
// import java.util.List;
// import java.util.Set;
// import java.util.stream.Collectors;
//
// /**
//  * @author xiongweitao
//  * @version V1.0 Created on 2021/6/21
//  * @title CalculateUtil
//  * @Description:
//  */
// public class CalculateUtil {
//
//     /**
//      * 计算到位覆盖
//      *
//      * @param positions
//      * @param calculator
//      * @param taskId
//      * @param userPosition
//      */
//     public static String calculatePatrolTask(List<List<Position>> positions, Calculator calculator, long taskId, Position userPosition) throws UnSupportedMethodException, InvalidParametersException {
//         // 集团化，根据任务所在子公司转换坐标
//         TraceConfigHandler traceConfigHandle = SpringUtil.getBean(TraceConfigHandler.class);
//         String eCode = calculator.getTaskModel().getECode();
//         // 坐标转换
//         if (positions != null) {
//             positions.forEach(positionList -> {
//                 positionList.forEach(position -> {
//                     traceConfigHandle.coordinateConversion(eCode, position);
//                 });
//             });
//         }
//         if (userPosition != null) {
//             traceConfigHandle.coordinateConversion(eCode, userPosition);
//         }
//         //对任务id加锁，一个任务 同时 只能有一个执行
//         synchronized (IdLockUtils.getLock("calculatePatrolTask-" + taskId)) {
//             if (positions == null) {
//                 return SpringContextHolder.getBean(ITaskComputeService.class).updateTaskArriveInfo(calculator, null, null);
//             }
//             long start = System.currentTimeMillis();
//             if (ListUtils.isEmpty(positions)) {
//                 return null;
//             }
//             if (null == calculator.getStartTime() || null == calculator.getEndTime()) {
//                 return null;
//             }
//             if (ListUtils.isEmpty(calculator.getTaskModel().getUserIds())) {
//                 // 没有用户信息不予计算
//                 return null;
//             }
//             //开始计算
//             for (List<Position> positionList : positions) {
//                 if (!nextCheck(positionList, calculator)) {
//                     break;
//                 }
//             }
//             long cost = System.currentTimeMillis() - start;
//             log.debug("任务ID={},计算耗时{}毫秒", calculator.getTaskModel().getTaskId(), cost);
//
//             //上报的轨迹点,用于手动到位
//             Position reportPosition = null;
//             if (userPosition != null) {
//                 reportPosition = positions.get(0).get(0);
//             }
//             //更新任务数据
//             return SpringContextHolder.getBean(ITaskComputeService.class).updateTaskArriveInfo(calculator, userPosition, reportPosition);
//         }
//     }
//
//
//     /**
//      * @param positionList 轨迹点
//      * @param calculator   计算类
//      */
//     public static boolean nextCheck(List<Position> positionList, Calculator calculator) {
//         if (ListUtils.isEmpty(positionList)) {
//             return true;
//         }
//
//         boolean isFirst = true;
//         // 循环, 每两个点为一组, 调用check方法进行计算
//         for (int i = 0, size = positionList.size(); i < size; i++) {
//             // 如果任务已经计算完成，不必继续循环计算
//             if (calculator.isFinish()) {
//                 return false;
//             }
//
//             Position position = positionList.get(i);
//             if (!calculator.validPosition(position)) {
//                 continue;
//             }
//             //最后一个轨迹的下一个为null
//             Position nextPosition = null;
//             if (i + 1 < size) {
//                 nextPosition = positionList.get(i + 1);
//                 if (!calculator.validPosition(nextPosition)) {
//                     nextPosition = null;
//                 }
//             } else {
//                 nextPosition = null;
//             }
//             // 两点插值计算
//             check(position, nextPosition, !isFirst, calculator);
//             isFirst = false;
//         }
//         return true;
//     }
//
//     /**
//      * @param startPosition 起始轨迹点
//      * @param endPosition   结束轨迹点
//      * @param calculator    计算类
//      * @param ignoreFirst   是否忽略第一个点，因上个循环存在两个以上的点时，下一个点已经被提前使用
//      */
//     public static void check(Position startPosition, Position endPosition, boolean ignoreFirst, Calculator calculator) {
//         // 找出点,线,面buffer中最小的buffer再除以2, 得到轨迹插值buffer
//         double buffer = Math.min(calculator.getPointBuffer(), calculator.getLineBuffer());
//         buffer = Math.min(buffer, calculator.getAreaBuffer());
//         buffer = buffer / 2;
//         // 步长为buffer,插值
//         List<Position> positionList = com.zzht.patrol.bp.calculate.utils.LineUtil.interpolationPosition(startPosition, endPosition, buffer);
//         boolean isFirst = true;
//         for (Position position : positionList) {
//             if (isFirst && ignoreFirst) {
//                 isFirst = false;
//                 continue;
//             }
//             //计算点
//             calculator.calculatePoint(position);
//             //计算线
//             calculator.calculateLine(position);
//             //计算面
//             calculator.calculateArea(position);
//         }
//     }
//
//
//     /**
//      * j计算出圈
//      *
//      * @param position
//      * @param calculator
//      * @param taskId
//      * @return
//      */
//     public static boolean calculateOutCirCle(Position position, Calculator calculator, Long taskId) throws UnSupportedMethodException, InvalidParametersException {
//         // 集团化，根据任务所在公司进行坐标转换
//         TraceConfigHandler traceConfigHandle = SpringUtil.getBean(TraceConfigHandler.class);
//         String eCode = calculator.getTaskModel().getECode();
//         traceConfigHandle.coordinateConversion(eCode, position);
//         //对任务id加锁，一个任务 同时 只能有一个执行
//         synchronized (IdLockUtils.getLock("calculateOutCirCle-" + taskId)) {
//             if (null == calculator || null == calculator.getStartTime() || null == calculator.getEndTime()) {
//                 return false;
//             }
//             if (ListUtils.isEmpty(calculator.getTaskModel().getUserIds())) {
//                 // 没有用户信息不予计算
//                 return false;
//             }
//             if (!com.zzht.patrol.bp.calculate.utils.ToolUtil.isToday(position.getGpsTime())) {
//                 //如果是历史轨迹，则不计算
//                 return false;
//             }
//             int outBuffer = SpringContextHolder.getBean(IConfigService.class).findOutBuffer();
//             //没有找到设备为true，找到了为false
//             Boolean pOut = calculator.calculateOutPoint(position, outBuffer);
//             Boolean lOut = calculator.calculateOutLine(position, outBuffer);
//             Boolean aOut = calculator.calculateOutArea(position, outBuffer);
//             if (pOut && lOut && aOut) {
//                 return true;
//             } else {
//                 return false;
//             }
//         }
//     }
//
//     /**
//      * 计算停滞
//      *
//      * @param positions
//      * @param userId
//      * @param userName
//      * @param tlist
//      */
//     public static void calculateStagnate(List<List<Position>> positions, Long userId, String userName, Set<Long> tlist) {
//         //对用户id加锁，一个用户 同时 只能有一个执行
//         synchronized (IdLockUtils.getLock("calculateStagnate-" + userId)) {
//             int factor = SpringContextHolder.getBean(IConfigService.class).findFactor();
//             double maxDist = SpringContextHolder.getBean(IConfigService.class).findMaxDist();
//             double maxDuration = SpringContextHolder.getBean(IConfigService.class).findMaxDuration();
//
//             //通过
//             StagnateCal model = StagnateBasket.getInstance().findClusterRectModel(userId.toString(), userName);
//             if (tlist.isEmpty()) {
//                 StagnateBasket.getInstance().addOverCache(model.getStagnation(), userId.toString());
//                 //移除
//                 StagnateBasket.getInstance().removesStayCache(userId.toString());
//                 return;
//             }
//
//             model.getStagnation().setTaskIds(StringUtils.join(tlist, ","));
//             for (List<Position> plist : positions) {
//                 for (Position p : plist) {
//                     //去除相邻两个重复点
//                     if (!com.zzht.patrol.bp.calculate.utils.ToolUtil.isToday(p.getGpsTime())) {
//                         //如果是历史轨迹，则不计算
//                         continue;
//                     }
//                     if (model.getStagnation().getEndTime() != null
//                             && !com.zzht.patrol.bp.calculate.utils.ToolUtil.judgeTodayTask(null, model.getStagnation().getEndTime(), null)) {
//                         StagnateBasket.getInstance().addOverCache(model.getStagnation(), userId.toString());
//                         //移除
//                         StagnateBasket.getInstance().removesStayCache(userId.toString());
//                         return;
//                     }
//                     // 过滤出是今天的轨迹，因为会出现前一天的点跟今天的点在一起计算的问题
//                     model.setCallist(model.getCallist().stream().filter(position -> com.zzht.patrol.bp.calculate.utils.ToolUtil.isToday(position.getGpsTime())).collect(Collectors.toList()));
//                     //1.判断A数组大小，小于5直接返回，只有至少5个点才参与计算
//                     if (model.getCallist().size() < factor) {
//                         model.getCallist().add(p);
//                         StagnateBasket.getInstance().updateIngCache(model, userId.toString(), null);
//                         continue;
//                     }
//
//                     //2.创建临时的数组，参与计算
//                     List<Position> temps = new ArrayList<>(model.getCallist());
//                     temps.add(p);
//                     Position[] tempArr = temps.toArray(new Position[0]);
//                     List<ClusterPoint> templist = PositionCluster.clusterByDistance(tempArr, maxDist, maxDuration);
//
//                     //3.如果结果list为空  ，则说明
//                     if (templist.isEmpty()) {
//                         model.getCallist().add(p);
//                         model.getUnlist().clear();
//                         StagnateBasket.getInstance().updateIngCache(model, userId.toString(), null);
//                         continue;
//                     }
//
//                     //4.判断临时计算出来的 停滞与 上一次计算的停滞是否相同
//                     if (StagnateBasket.judgeClusterPoint(model.getStagnation(), templist.get(0))) {
//                         model.getUnlist().add(p);
//                         if (model.getUnlist().size() > factor) {
//                             StagnateBasket.getInstance().addOverCache(model.getStagnation(), userId.toString());
//                             //创建新的停滞
//                             model.createNew(userId.toString(), userName);
//                         }
//                     } else {
//                         model.getCallist().add(p);
//                         model.getUnlist().clear();
//                         model.setClusterPoints(templist.get(0), userId.toString(), userName);
//                     }
//                     StagnateBasket.getInstance().updateIngCache(model, userId.toString(), null);
//                 }
//             }
//         }
//     }
// }
